package com.hulk.ratel.service;

import cn.hutool.core.bean.BeanUtil;

import com.google.common.base.Strings;

import com.google.common.base.Throwables;


import com.hulk.ratel.common.constant.enums.BussErrCode;
import com.hulk.ratel.common.constant.enums.TxnLogStatus;
import com.hulk.ratel.common.constant.enums.TxnProcessStep;
import com.hulk.ratel.common.exception.ManageRteException;

import com.hulk.ratel.common.util.DateUtil;
import com.hulk.ratel.common.util.IDWorkerRadix;
import com.hulk.ratel.component.R;
import com.hulk.ratel.constant.Constants;
import com.hulk.ratel.manage.bo.InitiativeScanPayReqBO;
import com.hulk.ratel.manage.bo.InitiativeScanPayRespBO;
import com.hulk.ratel.manage.bo.RouteReqBO;
import com.hulk.ratel.manage.bo.RouteRespBO;
import com.hulk.ratel.manage.org.InitiativeScanPayManager;
import com.hulk.ratel.persistence.entity.LogTxnPayRecord;
import com.hulk.ratel.persistence.entity.PartnerInfo;
import com.hulk.ratel.persistence.entity.Txncode;

import com.hulk.ratel.service.dto.InitiativeScanPayReqDTO;
import com.hulk.ratel.service.dto.InitiativeScanPayRespDTO;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;

/**
 * @Author: hulk
 * @E-mail: 29572320@qq.com
 * @Date: Create in 2018/8/31 下午10:14
 * @Verion: 1.0.0
 * @Modify by:
 * Class description 主扫支付交易业务实现类
 */
@Slf4j
@Service(value = "initiativeScanPayService")
public class InitiativeScanPayServiceImpl extends AbsServiceImpl implements InitiativeScanPayService {

    @Autowired
    private InitiativeScanPayManager initiativeScanPayManager;

    @Override
    public R<InitiativeScanPayRespDTO> excute(InitiativeScanPayReqDTO dto, String intCutDate,  String platformId) {
        log.info("InitiativeScanPayService<主扫> 请求参数：workId:{}, InitiativeScanPayReqDTO:{},intCutDate:{}", platformId, dto, intCutDate);

        LogTxnPayRecord record = new LogTxnPayRecord();
        InitiativeScanPayRespBO respBO;
        InitiativeScanPayRespDTO respDTO = new InitiativeScanPayRespDTO();
        try {
            intCutDate = Optional.ofNullable(intCutDate).orElse(DateUtil.getDateyyyyMMdd());
            String workId = Optional.ofNullable(platformId).orElse(IDWorkerRadix.getId());

            validateBean(dto, workId);

            String txnCode = dto.getHead().getTxnCode();
            String partnerNo = dto.getHead().getPartnerNo();
            String traceId = dto.getHead().getTraceId();

            //合作方信息校验
            PartnerInfo partnerInfo = checkPartner(partnerNo, workId);
            //交易权限校验
            Txncode txnCodeInfo = checkTxnCode(txnCode, workId);
            //交易重复性校验
            checkTxnLog(traceId, workId, partnerNo);
            //生成支付流水
            this.initTxnLog(record, partnerInfo, txnCodeInfo, dto, intCutDate, workId);

            //根据路由表获取上游机构号
            RouteReqBO routeReqBO = new RouteReqBO();
            routeReqBO.setPartnerNo(partnerNo);

            RouteRespBO routeRespBO = Optional.ofNullable(dispatchRouteService.dispatch(routeReqBO, workId)).orElseThrow(() -> new ManageRteException(workId, BussErrCode.E_900011));
            String orgCode = routeRespBO.getOrgCode();

            //生成BO
            InitiativeScanPayReqBO reqBO = new InitiativeScanPayReqBO();
            BeanUtil.copyProperties(dto, reqBO);
            reqBO.setPartnerNo(dto.getHead().getPartnerNo());
            reqBO.setTxnCode(dto.getHead().getTxnCode());
            reqBO.setWorkId(workId);
            //获取上游支付机构处理类进行支付
            respBO = initiativeScanPayManager.doPay(orgCode, dto.getHead().getTxnCode(), reqBO, record, workId);
            modifyTxnLog(record, respBO);
            log.info("InitiativeScanPayService<主扫> 返回参数：workId:{}, InitiativeScanPayRespDTO:{},intCutDate:{}", platformId, respDTO, intCutDate);
            if (respBO.getRespFlag()) {
                return R.ok(respDTO);
            } else {
                return R.fail(respBO.getRespCode(), respBO.getRespMsg());
            }
        } catch (Exception e) {
            log.error("InitiativeScanPayService<主扫>异常:{}", Throwables.getStackTraceAsString(e));
            throw e;
        }
    }

    /**
     * 支付流水初始化
     */
    private void initTxnLog(LogTxnPayRecord record,
                            PartnerInfo partnerInfo,
                            Txncode txnCode,
                            InitiativeScanPayReqDTO reqDto,
                            String intCutDate,
                            String workId
    ) {

        record.setId(Long.parseLong(workId));//主键生成
        record.setReversion(Long.valueOf(Constants.ZERO_INT));
        record.setIntCutDate(intCutDate);
        record.setWorkId(workId);
        record.setCallBackUrl(reqDto.getCallBackUrl());
        record.setVersion(reqDto.getHead().getVersion());
        record.setPartnerNo(partnerInfo.getPartnerNo());
        record.setMerchantCode(reqDto.getMerchantCode());//商户号
        record.setOverorgCode(reqDto.getOverOrgCode());//末端支付机构号
        record.setPartnerType(partnerInfo.getPartnerType());//合作方类型
        record.setTraceId(reqDto.getHead().getTraceId());
        record.setTxnType(txnCode.getTxnType());
        record.setTxnCode(txnCode.getTxnCode());
        record.setReqDate(reqDto.getHead().getReqDate());
        record.setReqTime(reqDto.getHead().getReqTime());
        if (!Strings.isNullOrEmpty(reqDto.getExpireTime())) {
            record.setExpireTime(Constants.ONE_DAY_MINUTES);
        } else {
            record.setExpireTime(Constants.ONE_DAY_MINUTES);
        }
        record.setTotalAmt(Integer.valueOf(reqDto.getTotalAmt()));
        record.setSubject(reqDto.getSubject());
        record.setDescription(reqDto.getDesc());
        record.setGoodsTag(reqDto.getGoodsTag());
        record.setBuyerPayAmt(null);
        record.setFavorAmt(null);
        record.setStep(TxnProcessStep.ACCEPTED.getValue());
        record.setStatus(TxnLogStatus.CREATED.getValue());
        record.setTerminalNo(reqDto.getTerminalNo());//用户号码
        record.setClientIp(reqDto.getTerminalIp());
        logTxnPayRecordRepository.save(record);

    }

    private void modifyTxnLog(LogTxnPayRecord record,
                              InitiativeScanPayRespBO respDTO
    ) {
        record.setRespDate(DateUtil.getDateyyyyMMdd());
        record.setReqTime(DateUtil.getDateyyyyMMddHHmmss());
        record.setRespCode(String.valueOf(respDTO.getRespCode()));
        record.setRespMsg(respDTO.getRespMsg());
        record.setQrCode(respDTO.getQrCode());

        if(String.valueOf(BussErrCode.S_0.getErrCode()).equals(record.getRespCode())){
            record.setStatus(TxnLogStatus.PROCESSING.getValue());
        }
        logTxnPayRecordRepository.updateById(record);


    }

}
